package while_lang.ast;

import java.util.Map;
import java.util.Random;

/** Categoría sintáctica de las expresiones de While. Éstas son todas las 
 *  construcciones del lenguaje que evalúan a un valor numérico, booleano o
 *  cualquier otro que se soporte. 
 *  Todas las clases que representan construcciones dentro de la categoria 
 *  deben heredar de esta clase.
 *  @author Leonardo Val.
 */
public abstract class Exp {
	
	/** Retorna un texto que de ser pasado por el parser construiría el mismo AST. 
	 */
	public abstract String unparse();
	
	/** Calculates the numbers required for the Halstead complexity measures.
	 *  @see <http://en.wikipedia.org/wiki/Halstead_complexity_measures>
	 */
	public abstract void halteadNumbers(Map<String, Integer> operands, Map<String, Integer> operators);
	
	/** Genera una instancia aleatoria de Exp. 
	 */
	public static Exp generate(Random random, int min, int max) {
		int i = min > 0 ? random.nextInt(10) + 1 : 
				max > 0 ? random.nextInt(11) : 
				0;
		switch (i) {
			case 0: return Constant.generate(random, min, max);
			case 1: return Ref.generate(random, min, max);
			case 2: return Addition.generate(random, min, max); 
			case 3: return Substraction.generate(random, min, max);
			case 4: return Multiplication.generate(random, min, max);
			case 5: return Division.generate(random, min, max);
			case 6: return CompEqual.generate(random, min, max);
			case 7: return CompEqualOrLess.generate(random, min, max);
			case 8: return Negation.generate(random, min, max);
			case 9: return Conjunction.generate(random, min, max);
			default: return ArrayExp.generate(random, min, max);
		} 
	}
	
	/** Todos los nodos del AST se convierten a string con una representación
	 *  textual similar a las llamadas a los constructores.
	 */
	@Override public abstract String toString();
	
	/** Se debe implementar para poder usar los nodos del AST con estructuras
	 *  como HashMap y HashSet.
	 */
	@Override public abstract int hashCode();
	
	/** Se debe implementar para poder usar los nodos del AST con estructuras
	 *  de datos.
	 */
	@Override public abstract boolean equals(Object obj);
}
